package com.bsj.power.common.util;


import lombok.extern.slf4j.Slf4j;

@Slf4j
public class ConvUtil {

    // etc: 22501030  -> 0xl6320AlE
    public static byte[] decimalTime2Array(String str) {
        //当长度为奇数补0
        if (str.length() % 2 == 1) {
            str = "0" + str;
        }
        int len = str.length() / 2;
        byte[] bytes = new byte[len];
        for (int j = 0; j < len ; j++) {
            byte temp = Byte.parseByte(str.substring(j * 2, j * 2 + 2));
            bytes[j] = temp;
        }
        return bytes;
    }
    //字符串转bcd码的字节数组
    public static byte[] str2bcd(String str) {
        //当长度为奇数补0
        if (str.length() % 2 == 1) {
            str = "0" + str;
        }
        int len = str.length() / 2;
        byte[] result = new byte[len];
        for (int i = 0; i < result.length; i++) {
            int hight = ((Integer.parseInt(str.substring(2 * i, 2 * i + 1)) << 4) & 0xf0);
            int low = (Integer.parseInt(str.substring(2 * i + 1, 2 * i + 2)) & 0xf);
            result[i] = (byte) (hight | low);
        }
        return result;
    }

    //时间转bcd    yyMMddHHmmss ---->  bcd[6]
    public static byte[] time2bcd(String time) {
        byte[] bytes = new byte[6];
        for (int i = 0; i < time.length() / 2; i++) {
            String heighLevel = time.substring(2 * i, 2 * i + 1);
            String lowLevel = time.substring(2 * i + 1, 2 * i + 2);
            Byte hByte = Byte.valueOf(heighLevel);
            Byte lByte = Byte.valueOf(lowLevel);
            bytes[i] = (byte) (((hByte & 0xf) << 4) | (lByte & 0xf));
        }
        return bytes;
    }

    // 网络字节序
    // 单WORD：先传高8位，再传低8位。
    // 双WORD：先传高24位，再传高16位，其次传高8位，最后传低8位。
    public static int getShortNetOrder(byte[] data, int offset) {
        if (data == null) {
            return 0;
        }

        int len = data.length;
        if (offset + 1 < len) {
            int high_8 = (Byte.toUnsignedInt(data[offset])) << 8;
            int low_8 = (Byte.toUnsignedInt(data[offset + 1]));
            int obj = high_8 + low_8;
            return obj;
        } else {
            return 0;
        }
    }

    // 主机字节序
    public static int getShortIntelOrder(byte[] data, int offset) {
        if (data == null) {
            return 0;
        }
        int len = data.length;
        if (offset + 1 < len) {
            int low_8 = Byte.toUnsignedInt(data[offset]);
            int high_8 = (Byte.toUnsignedInt(data[offset + 1])) << 8;
            int obj = high_8 + low_8;
            return obj;
        } else {
            return 0;
        }

    }

    public static long getIntNetOrder(byte[] data, int offset) {
        if (data == null) {
            return 0;
        }

        int len = data.length;
        if (offset + 3 < len) {
            long high_24 = (Byte.toUnsignedLong(data[offset])) << 24;
            long high_16 = (Byte.toUnsignedLong(data[offset + 1])) << 16;
            long high_8 = (Byte.toUnsignedLong(data[offset + 2])) << 8;
            long low_8 = (Byte.toUnsignedLong(data[offset + 3]));
            long obj = high_24 + high_16 + high_8 + low_8;
            return obj;
        } else {
            return 0;
        }
    }

    public static long getIntIntelOrder(byte[] data, int offset) {
        if (data == null) {
            return 0;
        }
        int len = data.length;
        if (offset + 3 < len) {
            long low_8 = Byte.toUnsignedLong(data[offset]);
            long high_8 = (Byte.toUnsignedLong(data[offset + 1])) << 8;
            long high_16 = (Byte.toUnsignedLong(data[offset + 2])) << 16;
            long high_24 = (Byte.toUnsignedLong(data[offset + 3])) << 24;
            long obj = high_24 + high_16 + high_8 + low_8;
            return obj;
        } else {
            return 0;
        }

    }


    // 写入数据，主机字节序
    public static void setShortHostOrder(byte[] data, int offset, int value) {
        data[offset] = (byte) (value & 0x00ff);
        data[offset + 1] = (byte) ((value & 0xff00) >> 8);
    }

    // 写入数据 网络字节序
    public static void setShortNetOrder(byte[] data, int offset, int value) {
        data[offset] = (byte) ((value & 0xff00) >> 8);
        data[offset + 1] = (byte) ((value & 0x00ff));
    }

    // 网络字节序
    public static void setIntNetOrder(byte[] data, int offset, long value) {
        data[offset] = (byte) ((value & 0xff000000) >> 24);
        data[offset + 1] = (byte) ((value & 0x00ff0000) >> 16);
        data[offset + 2] = (byte) ((value & 0x0000ff00) >> 8);
        data[offset + 3] = (byte) ((value & 0x000000ff) >> 0);
    }

    // 主机字节序
    public static void setIntHostOrder(byte[] data, int offset, long value) {
        data[offset + 3] = (byte) ((value & 0xff000000) >> 24);
        data[offset + 2] = (byte) ((value & 0x00ff0000) >> 16);
        data[offset + 1] = (byte) ((value & 0x0000ff00) >> 8);
        data[offset + 0] = (byte) ((value & 0x000000ff) >> 0);
    }

    // 将int存放在3字节的内存空间中，value 最高位可以看作0x00，不写内存
    public static void setIntNetOrder_3(byte[] data, int offset, long value) {
        data[offset] = (byte) ((value & 0x00ff0000) >> 16);
        data[offset + 1] = (byte) ((value & 0x0000ff00) >> 8);
        data[offset + 2] = (byte) ((value & 0x000000ff) >> 0);
    }

    public static void setDoubleNetOrder(byte[] data, int offset, double d) {
        long value = Double.doubleToRawLongBits(d);
        for (int i = 0; i < 8; i++) {
            data[offset + 7 - i] = (byte) ((value >> 8 * i) & 0xff);
        }
    }


    /**
     * @Title: setLongNetOrder @Description: 把Long放到内存 @param @param
     * data @param @param offset @param @param value @return void
     * 返回类型 @throws
     */
    public static void setLongNetOrder(byte[] data, int offset, long value) {
        for (int i = 0; i < 8; i++) {
            // long x6 = 0x00ff000000000000L;
            // long t0 = 0x00000000000000ffL << (8 * (7 - i));
            // long t1 = value & t0;
            // 注意：0x00000000000000ffL后面必须有个L
            data[offset + i] = (byte) ((value & (0x00000000000000ffL << (8 * (7 - i)))) >> (8 * (7 - i)));
        }
    }

    // 主机字节序
    public static void setLongHostOrder(byte[] data, int offset, long value) {
        for (int i = 0; i < 8; i++) {
            data[offset + (7 - i)] = (byte) ((value & (0x00000000000000ffL << (8 * (7 - i)))) >> (8 * (7 - i)));
        }
    }

    public static long getLongNetOrder(byte[] data, int offset) {
        long l = 0L;
        for (int i = 0; i < 8; i++) {
            l |= Byte.toUnsignedLong(data[offset + i]) << (8 * (7 - i));
        }
        return l;
    }

    public static long getLongIntelOrder(byte[] data, int offset) {
        long l = 0L;
        for (int i = 0; i < 8; i++) {
            l |= Byte.toUnsignedLong(data[offset + i]) << (8 * (i));
        }
        return l;
    }

    /**
     * 里程
     *
     * @param data
     * @param offset
     * @return
     */
    public static long getMileage(byte[] data, int offset) {
        long high_24 = (Byte.toUnsignedLong(data[offset])) << 24;
        long high_16 = (Byte.toUnsignedLong(data[offset + 1])) << 16;
        long high_8 = (Byte.toUnsignedLong(data[offset + 2])) << 8;
        long low_8 = (Byte.toUnsignedLong(data[offset + 3]));
        long obj = high_24 + high_16 + high_8 + low_8;
        return obj;
    }

    /**
     * @Title: dec2bcd @Description: 10进制转BCD @param @param
     * dec @param @return @return byte 返回类型 @throws
     */
    public static byte dec2bcd(byte dec) {
        int iVal = Byte.toUnsignedInt(dec);
        return (byte) ((iVal / 10 * 16) + (iVal % 10) & 0xff);
    }

    /**
     * @Title: int2bytes @Description: 这里用一句话描述这个方法的作用 @param @param
     * iVal @param @return @return byte[] 返回类型 @throws
     */
    public static byte[] int2bytes(int iVal) {
        byte arr[] = new byte[4];
        arr[0] = (byte) ((iVal & 0xff000000) >> 24);
        arr[1] = (byte) ((iVal & 0x00ff0000) >> 16);
        arr[2] = (byte) ((iVal & 0x0000ff00) >> 8);
        arr[3] = (byte) ((iVal & 0x000000ff) >> 0);
        return arr;
    }

    public static byte[] short2bytes(int iVal) {
        byte arr[] = new byte[2];
        arr[0] = (byte) ((iVal & 0x0000ff00) >> 8);
        arr[1] = (byte) ((iVal & 0x000000ff) >> 0);
        return arr;
    }

    //第一个字节转
    public static byte oneBytes(int iVal) {
        byte arr = (byte) ((iVal & 0x000000ff) >> 0);
        return arr;
    }

    /**
     * 基站源始数据转成字符串
     *
     * @param array 数组
     * @return
     */
    public static String lbsDataToString(byte[] array) {
        if (array == null) {
            log.info("Param is null");
            return null;
        }

        StringBuffer sb = new StringBuffer();
        int len = array.length;
        for (int i = 0; i < len; i++) {
            int src = array[i] & 0xFF;
            if (sb.length() > 0) {
                sb.append("-");
            }

            String strHex = Integer.toHexString(src);
            if (strHex.length() < 2) {
                strHex = "0" + strHex;
            }
            sb.append(strHex);
        }

        return sb.toString().toUpperCase();
    }

    /**
     * byte数组转ASCII码
     *
     * @param array
     * @return
     */
    public static String byteArrayToAscii(byte[] array) {
        if (array == null) {
            return null;
        }

        StringBuffer res = new StringBuffer();
        for (byte b : array) {
            char tmp = (char) b;
            res.append(tmp);
        }

        return res.toString();
    }

    /**
     * 校验：从包头开始到校验前一字节的所有字节异或
     *
     * @param array  数据
     * @param offset 包头所对应的索引
     * @param len    校验的数据长度
     * @return
     */
    public static byte CheckXor(byte[] array, int offset, int len) {
        if (array == null) {
            return 0;
        }
        byte n = 0;
        for (int i = offset; i < offset + len; i++) {
            n ^= array[i];
        }
        return n;
    }

    /**
     * 检测bitOffset位是否是1
     *
     * @param data
     * @param bitOffset
     * @return
     */

    public static boolean CheckBit(long data, int bitOffset) {
        int i = bitValue(data, bitOffset);
        return i == 1 ? true : false;
    }
    public static boolean CheckBit(int data, int bitOffset) {
        int ret = ((data) >> (bitOffset)) & 0x01;

        return ret == 1 ? true : false;

    }


    /**
     * 设置bitOffset位为1
     *
     * @param data
     * @param bitOffset
     * @return
     */
    public static int setBit(int data, int bitOffset) {
        data |= (0x1 << (bitOffset));
        return data;
    }

    public static long setBit(long data, int bitOffset) {
        data |= (0x1 << (bitOffset));
        return data;
    }

    public static long setBitToo(long n, int bitOffset) {
        long ret = 0;
        for (int i = 0; i <= bitOffset; i++) {
            ret |= (0x1 << (bitValue(n, i) == 1 ? i : 0));
        }
        return ret;
    }


    /**
     * 获取伪IP 4字节
     *
     * @param array
     * @param offset
     * @param len
     * @return
     */
    public static String getVip(byte[] array, int offset, int len) {
        StringBuffer vipStr = new StringBuffer();
        for (int i = offset; i < offset + len; i++) {
            if (vipStr.length() > 0 && !vipStr.toString().endsWith(".")) {
                vipStr.append(".");
            }

            vipStr.append(Byte.toUnsignedInt(array[i]));
        }

        return vipStr.toString();
    }

    /**
     * 把IP地址转化为int
     *
     * @param ipAddr
     * @return int
     */
    public static byte[] ipToBytesByReg(String ipAddr) {
        byte[] ret = new byte[4];
        try {
            String[] ipArr = ipAddr.split("\\.");
            ret[0] = (byte) (Integer.parseInt(ipArr[0]) & 0xFF);
            ret[1] = (byte) (Integer.parseInt(ipArr[1]) & 0xFF);
            ret[2] = (byte) (Integer.parseInt(ipArr[2]) & 0xFF);
            ret[3] = (byte) (Integer.parseInt(ipArr[3]) & 0xFF);
            return ret;
        } catch (Exception e) {
            throw new IllegalArgumentException(ipAddr + " is invalid IP");
        }
    }

    public static byte[] intToMinByteArray(int i) {
        byte[] result = new byte[4];
        // 由高位到低位
        result[3] = (byte) ((i >> 24) & 0xFF);
        result[2] = (byte) ((i >> 16) & 0xFF);
        result[1] = (byte) ((i >> 8) & 0xFF);
        result[0] = (byte) (i & 0xFF);
        return result;
    }

    public static byte[] shortToMinByteArray(int i) {
        byte[] result = new byte[2];
        // 由高位到低位
        result[1] = (byte) ((i >> 8) & 0xFF);
        result[0] = (byte) (i & 0xFF);
        return result;
    }

    public static int stringToInt(String str) {
        int result = 0;
        String[] strArr = str.split("\\.");
        for (int i = 3; i >= 0; i--) {
            int ip = Integer.parseInt(strArr[3 - i]);
            result += ip << (i * 8);
        }
        return result;
    }

    public static int byte_bcd_to_dec(byte bcd) {
        if (bcd > 0x99) {
            return 0;
        }
        int src = bcd & 0xFF;
        int high = (src / 16);
        int low = (src % 16);

        return (high * 10 + low);
    }

    public static int bcd2int(byte[] bcd) {
        if (bcd.length != 4) {
            return 0;
        }
        int value = 0;
        int dec = byte_bcd_to_dec(bcd[0]);
        value = dec;
        dec = byte_bcd_to_dec(bcd[1]);
        value = value * 100 + dec;
        dec = byte_bcd_to_dec(bcd[2]);
        value = value * 100 + dec;
        dec = byte_bcd_to_dec(bcd[3]);
        value = value * 100 + dec;
        return value;
    }

    // BCD  度分格式转 度
    public static double bcdPosDM2D(byte[] data, int offset) {
        if (data.length - offset < 4) {
            return 0;
        }
        byte[] srcData = new byte[4];
        System.arraycopy(data, offset, srcData, 0, 4);

        int intValue;
        double retValueD;
        srcData[0] &= 0x7f;
        intValue = bcd2int(srcData);
        retValueD = ((intValue / 100000) * 100000 + (double) (intValue % 100000) / 60 * 100) / 100000.0;   //度分转成度
        return retValueD;
    }

    /**
     * 求整数的二进制第几位的值
     *
     * @param n   整数
     * @param bit 第几位，从0开始
     * @return
     */
    public static int bitValue(long n, int bit) {
        return (int) ((n >> bit) & 0x01);
    }
    /**
     * bcd转字符串
     *
     * @param bcd
     * @return
     */
    public static String bcd2str(byte[] bcd) {
        String result = "";
        if (bcd == null) {
            return null;
        }
        for (byte b : bcd
        ) {
            int hight = (b & 0xf0) >> 4;
            int low = b & 0xf;
            result += (String.valueOf(hight) + String.valueOf(low));
        }
        return result;
    }
}
